package com.titaniume.java;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @program: JavaSenior
 * @description:
 * @author: renfei.huang
 * @create: 2021-11-02 00:04
 */

interface Human{

    String getBelief();

    void eat(String food);
}

class SuperMan implements Human{
    @Override
    public String getBelief() {
        return "I believe I can fly!";
    }

    @Override
    public void eat(String food) {
        System.out.println("我喜欢吃" + food);
    }
}


/*
* 要想实现动态代理,需要结局的问题？
*  问题一：如何根据加载到内存中的被代理类，动态的创建一个代理类及其对象
* 问题二：当通过代理类的对象调用方法a时，如何动态的去调用被代理类中的同名方法a。
*
* */

class ProxyFactory{
    //调用此方法，返回一个代理类的对象 解决问题一
    public static Object getProxyInstance(Object object){ //obj:被大力类的对象

        MyHInvocationHandler handler = new MyHInvocationHandler();
        handler.bind(object);
        return   Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(),handler);
    }
}

class  MyHInvocationHandler implements InvocationHandler{

    private  Object object; //需要使用被代理类的对象进行赋值

    public void bind(Object object){
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        HumaUtil humaUtil = new HumaUtil();

        //method: 即为代理类对象调用的方法，此方法也就为了被代理类对象调用的方法
        //obj:被代理类的对象
        humaUtil.method1();
        Object invoke = method.invoke(object, args);
        //上述方法返回值就组颇为当前类中的invake()的返回值
        humaUtil.method1();

        return invoke;
    }

    //当我们通过代理类的对象，调用方法a时候，就会自动的调用如下方法：invoke()
    //将被代理类要执行的方法a的功能就声明在invoke()中

}


public class ProxyTest {

    public static void main(String[] args) {

        SuperMan superMan = new SuperMan();
        //human ：代理类的对象
        Human human =(Human) ProxyFactory.getProxyInstance(superMan);
        //当通过代理类的对象调用方法时，会自动的调用被代理类中同名的方法
        human.getBelief();
        human.eat("牛肉");


        System.out.println("-----------------------");

        NikeClothFactory nikeClothFactory = new NikeClothFactory();
        ClothFactory clothFactory = (ClothFactory)ProxyFactory.getProxyInstance(nikeClothFactory);
        clothFactory.productCloth();
    }
}


class HumaUtil{

    public  void method1(){
        System.out.println("-------------------------通用的方法一---------------------------");
    }

    public  void methods2(){
        System.out.println("-------------------------通用的方法二---------------------------");
    }
}